/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package dao;

import dao.exceptions.NonexistentEntityException;
import dominio.Endereco;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import dominio.Cliente;
import java.util.ArrayList;
import java.util.List;
import dominio.Funcionario;
import dominio.Fornecedor;

/**
 *
 * @author Gutto
 */
public class ManterEnderecoDAO {

    public ManterEnderecoDAO() {
        emf = Persistence.createEntityManagerFactory("SIGITPU");
    }
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public void create(Endereco endereco) {
        if (endereco.getClienteList() == null) {
            endereco.setClienteList(new ArrayList<Cliente>());
        }
        if (endereco.getFuncionarioList() == null) {
            endereco.setFuncionarioList(new ArrayList<Funcionario>());
        }
        if (endereco.getFornecedorList() == null) {
            endereco.setFornecedorList(new ArrayList<Fornecedor>());
        }
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            List<Cliente> attachedClienteList = new ArrayList<Cliente>();
            for (Cliente clienteListClienteToAttach : endereco.getClienteList()) {
                clienteListClienteToAttach = em.getReference(clienteListClienteToAttach.getClass(), clienteListClienteToAttach.getCodigo());
                attachedClienteList.add(clienteListClienteToAttach);
            }
            endereco.setClienteList(attachedClienteList);
            List<Funcionario> attachedFuncionarioList = new ArrayList<Funcionario>();
            for (Funcionario funcionarioListFuncionarioToAttach : endereco.getFuncionarioList()) {
                funcionarioListFuncionarioToAttach = em.getReference(funcionarioListFuncionarioToAttach.getClass(), funcionarioListFuncionarioToAttach.getCodigoFuncionario());
                attachedFuncionarioList.add(funcionarioListFuncionarioToAttach);
            }
            endereco.setFuncionarioList(attachedFuncionarioList);
            List<Fornecedor> attachedFornecedorList = new ArrayList<Fornecedor>();
            for (Fornecedor fornecedorListFornecedorToAttach : endereco.getFornecedorList()) {
                fornecedorListFornecedorToAttach = em.getReference(fornecedorListFornecedorToAttach.getClass(), fornecedorListFornecedorToAttach.getCodigo());
                attachedFornecedorList.add(fornecedorListFornecedorToAttach);
            }
            endereco.setFornecedorList(attachedFornecedorList);
            em.persist(endereco);
            for (Cliente clienteListCliente : endereco.getClienteList()) {
                Endereco oldEnderecoOfClienteListCliente = clienteListCliente.getEndereco();
                clienteListCliente.setEndereco(endereco);
                clienteListCliente = em.merge(clienteListCliente);
                if (oldEnderecoOfClienteListCliente != null) {
                    oldEnderecoOfClienteListCliente.getClienteList().remove(clienteListCliente);
                    oldEnderecoOfClienteListCliente = em.merge(oldEnderecoOfClienteListCliente);
                }
            }
            for (Funcionario funcionarioListFuncionario : endereco.getFuncionarioList()) {
                Endereco oldEnderecoOfFuncionarioListFuncionario = funcionarioListFuncionario.getEndereco();
                funcionarioListFuncionario.setEndereco(endereco);
                funcionarioListFuncionario = em.merge(funcionarioListFuncionario);
                if (oldEnderecoOfFuncionarioListFuncionario != null) {
                    oldEnderecoOfFuncionarioListFuncionario.getFuncionarioList().remove(funcionarioListFuncionario);
                    oldEnderecoOfFuncionarioListFuncionario = em.merge(oldEnderecoOfFuncionarioListFuncionario);
                }
            }
            for (Fornecedor fornecedorListFornecedor : endereco.getFornecedorList()) {
                Endereco oldEnderecoOfFornecedorListFornecedor = fornecedorListFornecedor.getEndereco();
                fornecedorListFornecedor.setEndereco(endereco);
                fornecedorListFornecedor = em.merge(fornecedorListFornecedor);
                if (oldEnderecoOfFornecedorListFornecedor != null) {
                    oldEnderecoOfFornecedorListFornecedor.getFornecedorList().remove(fornecedorListFornecedor);
                    oldEnderecoOfFornecedorListFornecedor = em.merge(oldEnderecoOfFornecedorListFornecedor);
                }
            }
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(Endereco endereco) throws NonexistentEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Endereco persistentEndereco = em.find(Endereco.class, endereco.getId());
            List<Cliente> clienteListOld = persistentEndereco.getClienteList();
            List<Cliente> clienteListNew = endereco.getClienteList();
            List<Funcionario> funcionarioListOld = persistentEndereco.getFuncionarioList();
            List<Funcionario> funcionarioListNew = endereco.getFuncionarioList();
            List<Fornecedor> fornecedorListOld = persistentEndereco.getFornecedorList();
            List<Fornecedor> fornecedorListNew = endereco.getFornecedorList();
            List<Cliente> attachedClienteListNew = new ArrayList<Cliente>();
            for (Cliente clienteListNewClienteToAttach : clienteListNew) {
                clienteListNewClienteToAttach = em.getReference(clienteListNewClienteToAttach.getClass(), clienteListNewClienteToAttach.getCodigo());
                attachedClienteListNew.add(clienteListNewClienteToAttach);
            }
            clienteListNew = attachedClienteListNew;
            endereco.setClienteList(clienteListNew);
            List<Funcionario> attachedFuncionarioListNew = new ArrayList<Funcionario>();
            for (Funcionario funcionarioListNewFuncionarioToAttach : funcionarioListNew) {
                funcionarioListNewFuncionarioToAttach = em.getReference(funcionarioListNewFuncionarioToAttach.getClass(), funcionarioListNewFuncionarioToAttach.getCodigoFuncionario());
                attachedFuncionarioListNew.add(funcionarioListNewFuncionarioToAttach);
            }
            funcionarioListNew = attachedFuncionarioListNew;
            endereco.setFuncionarioList(funcionarioListNew);
            List<Fornecedor> attachedFornecedorListNew = new ArrayList<Fornecedor>();
            for (Fornecedor fornecedorListNewFornecedorToAttach : fornecedorListNew) {
                fornecedorListNewFornecedorToAttach = em.getReference(fornecedorListNewFornecedorToAttach.getClass(), fornecedorListNewFornecedorToAttach.getCodigo());
                attachedFornecedorListNew.add(fornecedorListNewFornecedorToAttach);
            }
            fornecedorListNew = attachedFornecedorListNew;
            endereco.setFornecedorList(fornecedorListNew);
            endereco = em.merge(endereco);
            for (Cliente clienteListOldCliente : clienteListOld) {
                if (!clienteListNew.contains(clienteListOldCliente)) {
                    clienteListOldCliente.setEndereco(null);
                    clienteListOldCliente = em.merge(clienteListOldCliente);
                }
            }
            for (Cliente clienteListNewCliente : clienteListNew) {
                if (!clienteListOld.contains(clienteListNewCliente)) {
                    Endereco oldEnderecoOfClienteListNewCliente = clienteListNewCliente.getEndereco();
                    clienteListNewCliente.setEndereco(endereco);
                    clienteListNewCliente = em.merge(clienteListNewCliente);
                    if (oldEnderecoOfClienteListNewCliente != null && !oldEnderecoOfClienteListNewCliente.equals(endereco)) {
                        oldEnderecoOfClienteListNewCliente.getClienteList().remove(clienteListNewCliente);
                        oldEnderecoOfClienteListNewCliente = em.merge(oldEnderecoOfClienteListNewCliente);
                    }
                }
            }
            for (Funcionario funcionarioListOldFuncionario : funcionarioListOld) {
                if (!funcionarioListNew.contains(funcionarioListOldFuncionario)) {
                    funcionarioListOldFuncionario.setEndereco(null);
                    funcionarioListOldFuncionario = em.merge(funcionarioListOldFuncionario);
                }
            }
            for (Funcionario funcionarioListNewFuncionario : funcionarioListNew) {
                if (!funcionarioListOld.contains(funcionarioListNewFuncionario)) {
                    Endereco oldEnderecoOfFuncionarioListNewFuncionario = funcionarioListNewFuncionario.getEndereco();
                    funcionarioListNewFuncionario.setEndereco(endereco);
                    funcionarioListNewFuncionario = em.merge(funcionarioListNewFuncionario);
                    if (oldEnderecoOfFuncionarioListNewFuncionario != null && !oldEnderecoOfFuncionarioListNewFuncionario.equals(endereco)) {
                        oldEnderecoOfFuncionarioListNewFuncionario.getFuncionarioList().remove(funcionarioListNewFuncionario);
                        oldEnderecoOfFuncionarioListNewFuncionario = em.merge(oldEnderecoOfFuncionarioListNewFuncionario);
                    }
                }
            }
            for (Fornecedor fornecedorListOldFornecedor : fornecedorListOld) {
                if (!fornecedorListNew.contains(fornecedorListOldFornecedor)) {
                    fornecedorListOldFornecedor.setEndereco(null);
                    fornecedorListOldFornecedor = em.merge(fornecedorListOldFornecedor);
                }
            }
            for (Fornecedor fornecedorListNewFornecedor : fornecedorListNew) {
                if (!fornecedorListOld.contains(fornecedorListNewFornecedor)) {
                    Endereco oldEnderecoOfFornecedorListNewFornecedor = fornecedorListNewFornecedor.getEndereco();
                    fornecedorListNewFornecedor.setEndereco(endereco);
                    fornecedorListNewFornecedor = em.merge(fornecedorListNewFornecedor);
                    if (oldEnderecoOfFornecedorListNewFornecedor != null && !oldEnderecoOfFornecedorListNewFornecedor.equals(endereco)) {
                        oldEnderecoOfFornecedorListNewFornecedor.getFornecedorList().remove(fornecedorListNewFornecedor);
                        oldEnderecoOfFornecedorListNewFornecedor = em.merge(oldEnderecoOfFornecedorListNewFornecedor);
                    }
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                Integer id = endereco.getId();
                if (findEndereco(id) == null) {
                    throw new NonexistentEntityException("The endereco with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(Integer id) throws NonexistentEntityException {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Endereco endereco;
            try {
                endereco = em.getReference(Endereco.class, id);
                endereco.getId();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The endereco with id " + id + " no longer exists.", enfe);
            }
            List<Cliente> clienteList = endereco.getClienteList();
            for (Cliente clienteListCliente : clienteList) {
                clienteListCliente.setEndereco(null);
                clienteListCliente = em.merge(clienteListCliente);
            }
            List<Funcionario> funcionarioList = endereco.getFuncionarioList();
            for (Funcionario funcionarioListFuncionario : funcionarioList) {
                funcionarioListFuncionario.setEndereco(null);
                funcionarioListFuncionario = em.merge(funcionarioListFuncionario);
            }
            List<Fornecedor> fornecedorList = endereco.getFornecedorList();
            for (Fornecedor fornecedorListFornecedor : fornecedorList) {
                fornecedorListFornecedor.setEndereco(null);
                fornecedorListFornecedor = em.merge(fornecedorListFornecedor);
            }
            em.remove(endereco);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<Endereco> findEnderecoEntities() {
        return findEnderecoEntities(true, -1, -1);
    }

    public List<Endereco> findEnderecoEntities(int maxResults, int firstResult) {
        return findEnderecoEntities(false, maxResults, firstResult);
    }

    private List<Endereco> findEnderecoEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            cq.select(cq.from(Endereco.class));
            Query q = em.createQuery(cq);
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public Endereco findEndereco(Integer id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Endereco.class, id);
        } finally {
            em.close();
        }
    }

    public int getEnderecoCount() {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            Root<Endereco> rt = cq.from(Endereco.class);
            cq.select(em.getCriteriaBuilder().count(rt));
            Query q = em.createQuery(cq);
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }

}
